package com.configtools.controller;

import com.configtools.service.ExcelFileService;
import com.configtools.service.ConfigService;
import com.configtools.service.ExcelParserService;
import com.configtools.service.CodeGeneratorService;
import com.configtools.model.ConfigSettings;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.DirectoryChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;


import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;

/**
 * 主界面控制器
 * 
 * @author ConfigTools Team
 * @version 1.0.0
 */
@Slf4j
public class MainController implements Initializable {

    // ================ 菜单栏组件 ================
    @FXML
    private MenuBar menuBar;
    
    @FXML
    private Menu configMenu;
    
    @FXML
    private Menu helpMenu;
    
    @FXML
    private MenuItem configMenuItem;
    
    @FXML
    private MenuItem helpMenuItem;
    
    @FXML
    private Button selectAllButton;
    
    @FXML
    private Button unselectAllButton;

    // ================ 左侧文件显示区域 ================
    @FXML
    private TableView<ExcelFileInfo> fileTableView;
    
    @FXML
    private TableColumn<ExcelFileInfo, Boolean> selectColumn;
    
    @FXML
    private TableColumn<ExcelFileInfo, String> fileNameColumn;
    
    @FXML
    private TableColumn<ExcelFileInfo, String> statusColumn;

    // ================ 右侧操作控制区域 ================
    @FXML
    private TextField excelDirectoryField;
    
    @FXML
    private Button selectDirectoryButton;
    
    @FXML
    private TextField outputDirectoryField;
    
    @FXML
    private Button browseOutputButton;
    
    @FXML
    private Button refreshButton;
    
    @FXML
    private Button clearLogButton;
    
    @FXML
    private Button generateJavaButton;

    // ================ 日志显示区域 ================
    @FXML
    private TextArea logTextArea;

    // ================ 数据模型 ================
    private ObservableList<ExcelFileInfo> fileList = FXCollections.observableArrayList();
    
    // ================ 服务实例 ================
    private ExcelFileService excelFileService;
    private ConfigService configService;
    private ExcelParserService excelParserService;
    private CodeGeneratorService codeGeneratorService;
    
    // ================ 状态变量 ================
    private String currentExcelDirectory = null;
    private String currentOutputDirectory = null;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        log.info("初始化主界面控制器...");
        
        // 初始化服务实例
        excelFileService = new ExcelFileService();
        configService = new ConfigService();
        excelParserService = new ExcelParserService();
        codeGeneratorService = new CodeGeneratorService();
        
        // 初始化文件表格
        initializeFileTable();
        
        // 初始化控件状态
        initializeControls();
        
        // 设置事件处理器
        setupEventHandlers();
        
        // 加载配置并应用已保存的目录设置
        loadSavedDirectorySettings();
        
        log.info("主界面控制器初始化完成");
    }
    
    /**
     * 获取选中的Excel文件列表
     * 
     * @return 选中的Excel文件列表
     */
    private List<File> getSelectedExcelFiles() {
        List<File> selectedFiles = new ArrayList<>();
        
        if (currentExcelDirectory == null || currentExcelDirectory.trim().isEmpty()) {
            return selectedFiles;
        }
        
        File excelDir = new File(currentExcelDirectory);
        if (!excelDir.exists() || !excelDir.isDirectory()) {
            return selectedFiles;
        }
        
        // 从文件列表中获取选中的文件
        for (ExcelFileInfo fileInfo : fileList) {
            if (fileInfo.isSelected()) {
                File excelFile = new File(excelDir, fileInfo.getFileName());
                if (excelFile.exists() && isExcelFile(excelFile)) {
                    selectedFiles.add(excelFile);
                }
            }
        }
        
        return selectedFiles;
    }
    
    /**
     * 检查是否为Excel文件
     * 
     * @param file 文件
     * @return 是否为Excel文件
     */
    private boolean isExcelFile(File file) {
        String fileName = file.getName().toLowerCase();
        return fileName.endsWith(".xlsx") || fileName.endsWith(".xls");
    }

    /**
     * 初始化文件表格
     */
    private void initializeFileTable() {
        log.debug("初始化文件表格...");
        
        // 设置表格数据源
        fileTableView.setItems(fileList);
        
        // 配置选择列
        selectColumn.setCellValueFactory(new PropertyValueFactory<>("selected"));
        selectColumn.setCellFactory(CheckBoxTableCell.forTableColumn(selectColumn));
        selectColumn.setEditable(true);
        selectColumn.setResizable(false);
        selectColumn.setPrefWidth(60);
        
        // 配置文件名列
        fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("fileName"));
        fileNameColumn.setPrefWidth(200);
        
        // 配置状态列
        statusColumn.setCellValueFactory(new PropertyValueFactory<>("status"));
        statusColumn.setPrefWidth(80);
        
        // 设置表格为可编辑（用于复选框）
        fileTableView.setEditable(true);
        
        // 设置行工厂，用于双击事件
        fileTableView.setRowFactory(tv -> {
            TableRow<ExcelFileInfo> row = new TableRow<>();
            row.setOnMouseClicked(event -> {
                if (event.getClickCount() == 2 && !row.isEmpty()) {
                    onFileDoubleClick(row.getItem());
                }
            });
            return row;
        });
        
        log.debug("文件表格初始化完成");
    }

    /**
     * 初始化控件状态
     */
    private void initializeControls() {
        log.debug("初始化控件状态...");
        
        // 设置默认路径
        excelDirectoryField.setText("请选择Excel文件目录...");
        outputDirectoryField.setText("请选择Java代码输出目录...");
        
        // 初始化日志区域
        logTextArea.setEditable(false);
        logTextArea.setWrapText(true);
        
        // 添加初始日志
        appendLog("INFO", "ConfigTools 已启动，等待用户操作...");
        
        log.debug("控件状态初始化完成");
    }

    /**
     * 设置事件处理器
     */
    private void setupEventHandlers() {
        log.debug("设置事件处理器...");
        
        // 菜单事件
        configMenuItem.setOnAction(e -> onConfigMenuClick());
        helpMenuItem.setOnAction(e -> onHelpMenuClick());
        
        // 按钮事件
        selectAllButton.setOnAction(e -> onSelectAllClick());
        unselectAllButton.setOnAction(e -> onUnselectAllClick());
        selectDirectoryButton.setOnAction(e -> onSelectDirectoryClick());
        browseOutputButton.setOnAction(e -> onBrowseOutputClick());
        refreshButton.setOnAction(e -> onRefreshClick());
        clearLogButton.setOnAction(e -> onClearLogClick());
        generateJavaButton.setOnAction(e -> onGenerateJavaClick());
        
        log.debug("事件处理器设置完成");
    }

    // ================ 菜单事件处理 ================
    
    /**
     * 配置菜单点击事件
     */
    private void onConfigMenuClick() {
        log.info("用户点击配置菜单");
        appendLog("INFO", "打开配置对话框...");
        
        try {
            showConfigDialog();
        } catch (Exception e) {
            log.error("打开配置对话框失败", e);
            appendLog("ERROR", "打开配置对话框失败: " + e.getMessage());
        }
    }

    /**
     * 帮助菜单点击事件
     */
    private void onHelpMenuClick() {
        log.info("用户点击帮助菜单");
        appendLog("INFO", "显示帮助信息...");
        
        // TODO: 实现帮助对话框
        // showHelpDialog();
        
        appendLog("INFO", "帮助对话框功能待实现");
    }

    // ================ 文件操作事件处理 ================
    
    /**
     * 全选按钮点击事件
     */
    private void onSelectAllClick() {
        log.info("用户点击全选按钮");
        
        if (fileList.isEmpty()) {
            appendLog("WARNING", "没有可选择的文件");
            return;
        }
        
        fileList.forEach(file -> file.setSelected(true));
        fileTableView.refresh();
        
        long selectedCount = fileList.stream().filter(ExcelFileInfo::isSelected).count();
        appendLog("SUCCESS", String.format("已全选 %d 个文件", selectedCount));
    }

    /**
     * 反选按钮点击事件
     */
    private void onUnselectAllClick() {
        log.info("用户点击反选按钮");
        
        if (fileList.isEmpty()) {
            appendLog("WARNING", "没有可选择的文件");
            return;
        }
        
        fileList.forEach(file -> file.setSelected(false));
        fileTableView.refresh();
        
        appendLog("SUCCESS", "已取消选择所有文件");
    }

    /**
     * 文件双击事件
     */
    private void onFileDoubleClick(ExcelFileInfo fileInfo) {
        log.info("用户双击文件: {}", fileInfo.getFileName());
        
        // TODO: 实现文件详情查看
        // showFileDetailDialog(fileInfo);
        
        appendLog("INFO", "查看文件详情功能待实现: " + fileInfo.getFileName());
    }

    // ================ 目录操作事件处理 ================
    
    /**
     * 选择Excel目录按钮点击事件
     */
    private void onSelectDirectoryClick() {
        log.info("用户点击选择Excel目录按钮");
        appendLog("INFO", "打开目录选择对话框...");
        
        try {
            DirectoryChooser directoryChooser = new DirectoryChooser();
            directoryChooser.setTitle("选择Excel文件目录");
            
            // 如果之前已选择过目录，设置为初始目录
            if (currentExcelDirectory != null) {
                File initialDir = new File(currentExcelDirectory);
                if (initialDir.exists() && initialDir.isDirectory()) {
                    directoryChooser.setInitialDirectory(initialDir);
                }
            }
            
            // 获取当前窗口作为父窗口
            Stage stage = (Stage) selectDirectoryButton.getScene().getWindow();
            File selectedDirectory = directoryChooser.showDialog(stage);
            
            if (selectedDirectory != null) {
                String directoryPath = selectedDirectory.getAbsolutePath();
                currentExcelDirectory = directoryPath;
                excelDirectoryField.setText(directoryPath);
                
                // 更新配置服务中的历史记录
                configService.updateLastExcelDirectory(directoryPath);
                
                appendLog("SUCCESS", "已选择Excel目录: " + directoryPath);
                
                // 自动扫描目录中的Excel文件
                scanExcelFilesInDirectory(directoryPath);
            } else {
                appendLog("INFO", "用户取消了目录选择");
            }
            
        } catch (Exception e) {
            log.error("选择Excel目录时发生错误", e);
            appendLog("ERROR", "选择目录失败: " + e.getMessage());
        }
    }

    /**
     * 浏览输出目录按钮点击事件
     */
    private void onBrowseOutputClick() {
        log.info("用户点击浏览输出目录按钮");
        appendLog("INFO", "打开输出目录选择对话框...");
        
        try {
            DirectoryChooser directoryChooser = new DirectoryChooser();
            directoryChooser.setTitle("选择Java代码输出目录");
            
            // 如果之前已选择过目录，设置为初始目录
            if (currentOutputDirectory != null) {
                File initialDir = new File(currentOutputDirectory);
                if (initialDir.exists() && initialDir.isDirectory()) {
                    directoryChooser.setInitialDirectory(initialDir);
                }
            }
            
            // 获取当前窗口作为父窗口
            Stage stage = (Stage) browseOutputButton.getScene().getWindow();
            File selectedDirectory = directoryChooser.showDialog(stage);
            
            if (selectedDirectory != null) {
                String directoryPath = selectedDirectory.getAbsolutePath();
                currentOutputDirectory = directoryPath;
                outputDirectoryField.setText(directoryPath);
                
                // 更新配置服务中的历史记录
                configService.updateLastOutputDirectory(directoryPath);
                
                appendLog("SUCCESS", "已选择输出目录: " + directoryPath);
            } else {
                appendLog("INFO", "用户取消了输出目录选择");
            }
            
        } catch (Exception e) {
            log.error("选择输出目录时发生错误", e);
            appendLog("ERROR", "选择输出目录失败: " + e.getMessage());
        }
    }

    // ================ 操作按钮事件处理 ================
    
    /**
     * 刷新按钮点击事件
     */
    private void onRefreshClick() {
        log.info("用户点击刷新按钮");
        appendLog("INFO", "开始刷新文件列表...");
        
        if (currentExcelDirectory == null || currentExcelDirectory.trim().isEmpty()) {
            appendLog("WARNING", "请先选择Excel文件目录");
            return;
        }
        
        // 重新扫描当前目录
        scanExcelFilesInDirectory(currentExcelDirectory);
    }

    /**
     * 清除日志按钮点击事件
     */
    private void onClearLogClick() {
        log.info("用户点击清除日志按钮");
        
        // 清除日志区域内容
        logTextArea.clear();
        appendLog("INFO", "日志已清除");
    }

    /**
     * 生成Java代码按钮点击事件
     */
    private void onGenerateJavaClick() {
        log.info("用户点击生成Java代码按钮");
        appendLog("INFO", "开始生成Java代码...");
        
        try {
            // 验证选中的文件
            List<File> selectedFiles = getSelectedExcelFiles();
            if (selectedFiles.isEmpty()) {
                appendLog("WARNING", "请先选择要处理的Excel文件");
                return;
            }
            
            // 验证输出目录
            if (currentOutputDirectory == null || currentOutputDirectory.trim().isEmpty()) {
                appendLog("WARNING", "请先选择输出目录");
                return;
            }
            
            // 获取配置信息
            ConfigSettings settings = configService.getCurrentSettings();
            String packageName = settings.getPackageName();
            String author = settings.getAuthorName();
            
            appendLog("INFO", String.format("开始处理 %d 个Excel文件", selectedFiles.size()));
            appendLog("INFO", "输出目录: " + currentOutputDirectory);
            appendLog("INFO", "包名: " + packageName);
            
            // 解析Excel文件
            List<com.configtools.model.ExcelSheet> allSheets = new ArrayList<>();
            for (File excelFile : selectedFiles) {
                try {
                    appendLog("INFO", "正在解析文件: " + excelFile.getName());
                    List<com.configtools.model.ExcelSheet> sheets = excelParserService.parseExcelFile(excelFile);
                    allSheets.addAll(sheets);
                    appendLog("SUCCESS", "文件解析成功: " + excelFile.getName());
                } catch (Exception e) {
                    log.error("解析Excel文件失败: {}", excelFile.getName(), e);
                    appendLog("ERROR", "文件解析失败: " + excelFile.getName() + " - " + e.getMessage());
                }
            }
            
            if (allSheets.isEmpty()) {
                appendLog("WARNING", "没有找到有效的配置表");
                return;
            }
            
            appendLog("INFO", String.format("共解析 %d 个配置表", allSheets.size()));
            
            // 生成Java代码
            codeGeneratorService.generateJavaCode(allSheets, currentOutputDirectory, packageName, author);
            
            appendLog("SUCCESS", "Java代码生成完成！");
            appendLog("INFO", "请查看输出目录: " + currentOutputDirectory);
            
        } catch (Exception e) {
            log.error("生成Java代码失败", e);
            appendLog("ERROR", "生成Java代码失败: " + e.getMessage());
        }
    }

    // ================ 配置对话框相关方法 ================
    
    /**
     * 显示配置对话框
     */
    private void showConfigDialog() throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/ConfigDialog.fxml"));
        Parent root = loader.load();
        
        // 获取控制器实例
        ConfigDialogController controller = loader.getController();
        
        // 注入配置服务
        controller.setConfigService(configService);
        
        // 创建配置对话框窗口
        Stage configStage = new Stage();
        configStage.setTitle("系统配置");
        configStage.initModality(Modality.WINDOW_MODAL);
        configStage.initOwner(selectDirectoryButton.getScene().getWindow());
        configStage.setResizable(false);
        
        // 创建场景并应用样式
        Scene scene = new Scene(root);
        scene.getStylesheets().add(getClass().getResource("/css/config-dialog.css").toExternalForm());
        configStage.setScene(scene);
        
        // 显示对话框并处理结果
        controller.showDialog(configStage, this::onConfigUpdated);
        
        log.info("配置对话框已显示");
    }
    
    /**
     * 加载保存的目录设置
     */
    private void loadSavedDirectorySettings() {
        log.info("正在加载保存的目录设置...");
        
        try {
            ConfigSettings currentSettings = configService.getCurrentSettings();
            
            // 如果启用了自动加载上次目录功能
            if (currentSettings.isAutoLoadLastDirectory()) {
                // 加载上次的Excel目录
                String lastExcelDir = currentSettings.getLastExcelDirectory();
                if (lastExcelDir != null && !lastExcelDir.trim().isEmpty()) {
                    File excelDir = new File(lastExcelDir);
                    if (excelDir.exists() && excelDir.isDirectory()) {
                        currentExcelDirectory = lastExcelDir;
                        excelDirectoryField.setText(lastExcelDir);
                        appendLog("INFO", "已自动加载Excel目录: " + lastExcelDir);
                        
                        // 自动扫描Excel文件
                        scanExcelFilesInDirectory(lastExcelDir);
                    } else {
                        appendLog("WARNING", "上次保存的Excel目录不存在: " + lastExcelDir);
                    }
                }
                
                // 加载上次的输出目录
                String lastOutputDir = currentSettings.getLastOutputDirectory();
                if (lastOutputDir != null && !lastOutputDir.trim().isEmpty()) {
                    File outputDir = new File(lastOutputDir);
                    if (outputDir.exists() && outputDir.isDirectory()) {
                        currentOutputDirectory = lastOutputDir;
                        outputDirectoryField.setText(lastOutputDir);
                        appendLog("INFO", "已自动加载输出目录: " + lastOutputDir);
                    } else {
                        appendLog("WARNING", "上次保存的输出目录不存在: " + lastOutputDir);
                    }
                }
            } else {
                appendLog("INFO", "自动加载目录功能已禁用");
            }
            
        } catch (Exception e) {
            log.error("加载保存的目录设置时发生错误", e);
            appendLog("ERROR", "加载目录设置失败: " + e.getMessage());
        }
    }
    
    /**
     * 配置更新回调
     */
    private void onConfigUpdated() {
        appendLog("SUCCESS", "配置已更新");
        
        // 加载新配置，更新界面状态
        ConfigSettings currentSettings = configService.getCurrentSettings();
        
        // 如果启用了自动加载上次目录，则应用相关设置
        if (currentSettings.isAutoLoadLastDirectory()) {
            // 加载上次的Excel目录
            String lastExcelDir = currentSettings.getLastExcelDirectory();
            if (lastExcelDir != null && !lastExcelDir.isEmpty() && 
                new File(lastExcelDir).exists()) {
                currentExcelDirectory = lastExcelDir;
                excelDirectoryField.setText(lastExcelDir);
                appendLog("INFO", "已自动加载上次的Excel目录: " + lastExcelDir);
            }
            
            // 加载上次的输出目录
            String lastOutputDir = currentSettings.getLastOutputDirectory();
            if (lastOutputDir != null && !lastOutputDir.isEmpty() && 
                new File(lastOutputDir).exists()) {
                currentOutputDirectory = lastOutputDir;
                outputDirectoryField.setText(lastOutputDir);
                appendLog("INFO", "已自动加载上次的输出目录: " + lastOutputDir);
            }
        }
        
        appendLog("INFO", "配置应用完成");
    }
    
    // ================ 工具方法 ================
    
    /**
     * 添加日志信息
     * 
     * @param level 日志级别 (INFO, SUCCESS, ERROR, WARNING)
     * @param message 日志消息
     */
    private void appendLog(String level, String message) {
        String timestamp = java.time.LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        
        String logEntry = String.format("[%s] %s: %s%n", timestamp, level, message);
        
        // 在JavaFX应用线程中更新UI
        javafx.application.Platform.runLater(() -> {
            logTextArea.appendText(logEntry);
            
            // 自动滚动到底部
            logTextArea.setScrollTop(Double.MAX_VALUE);
        });
    }
    
    /**
     * 扫描指定目录中的Excel文件
     * 
     * @param directoryPath 目录路径
     */
    private void scanExcelFilesInDirectory(String directoryPath) {
        log.info("开始扫描目录: {}", directoryPath);
        appendLog("INFO", "正在扫描目录: " + directoryPath);
        
        // 使用异步方式扫描文件，避免阻塞UI
        CompletableFuture.supplyAsync(() -> {
            try {
                return excelFileService.scanExcelFiles(directoryPath);
            } catch (Exception e) {
                log.error("扫描Excel文件时发生错误", e);
                Platform.runLater(() -> appendLog("ERROR", "扫描文件失败: " + e.getMessage()));
                return java.util.Collections.<File>emptyList();
            }
        }).thenAccept(excelFiles -> {
            // 在JavaFX应用线程中更新UI
            Platform.runLater(() -> {
                // 清空现有文件列表
                fileList.clear();
                
                if (excelFiles.isEmpty()) {
                    appendLog("WARNING", "在目录中未发现Excel文件");
                } else {
                    // 添加扫描到的文件到列表
                    for (File file : excelFiles) {
                        ExcelFileInfo fileInfo = new ExcelFileInfo(file.getName(), "未解析");
                        fileInfo.setSelected(true); // 默认选中
                        fileList.add(fileInfo);
                    }
                    
                    appendLog("SUCCESS", String.format("发现 %d 个Excel文件", excelFiles.size()));
                }
                
                // 刷新表格视图
                fileTableView.refresh();
            });
        }).exceptionally(throwable -> {
            log.error("异步扫描文件时发生异常", throwable);
            Platform.runLater(() -> appendLog("ERROR", "扫描过程发生异常: " + throwable.getMessage()));
            return null;
        });
    }

    // ================ 内部数据模型 ================
    
    /**
     * Excel文件信息数据模型
     */
    public static class ExcelFileInfo {
        private javafx.beans.property.BooleanProperty selected = new javafx.beans.property.SimpleBooleanProperty(false);
        private javafx.beans.property.StringProperty fileName = new javafx.beans.property.SimpleStringProperty();
        private javafx.beans.property.StringProperty status = new javafx.beans.property.SimpleStringProperty();

        public ExcelFileInfo() {}

        public ExcelFileInfo(String fileName, String status) {
            setFileName(fileName);
            setStatus(status);
        }

        // Selected属性
        public boolean isSelected() { return selected.get(); }
        public void setSelected(boolean selected) { this.selected.set(selected); }
        public javafx.beans.property.BooleanProperty selectedProperty() { return selected; }

        // FileName属性
        public String getFileName() { return fileName.get(); }
        public void setFileName(String fileName) { this.fileName.set(fileName); }
        public javafx.beans.property.StringProperty fileNameProperty() { return fileName; }

        // Status属性
        public String getStatus() { return status.get(); }
        public void setStatus(String status) { this.status.set(status); }
        public javafx.beans.property.StringProperty statusProperty() { return status; }
    }
}
